package com.dl.base.api

import com.dl.base.AppContext
import com.dl.base.api.websocket.WebSocketWorkerImpl
import com.google.gson.GsonBuilder
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Response
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.io.IOException
import java.lang.reflect.Type
import java.util.concurrent.TimeUnit

open class BaseNet {
    open val apiUrl = AppContext.url
    private val readTimeOut = 10L
    private val connectTimeout = 5L
    private val writeTimeout = 10L
    private val pingInterval = 120L

    private var okHttpClient: OkHttpClient? = null

    val retrofit: Retrofit by lazy {
        retrofitBuilder().build()
    }

    val webSocket by lazy { WebSocketWorkerImpl(okHttpClient(), 5, TimeUnit.SECONDS) }

    open fun retrofitBuilder(baseUrl: String = apiUrl): Retrofit.Builder = Retrofit.Builder()
        .baseUrl(baseUrl)
        .addConverterFactory(
            GsonConverterFactory.create(
                getGsonBuilder().create()
            )
        )
        .client(okHttpClient())

    open fun okHttpClient(): OkHttpClient {
        if (okHttpClient == null) {
            okHttpClient = OkHttpNotSSL.getNotSSLUnsafeOkHttpClient()
                .readTimeout(readTimeOut, TimeUnit.SECONDS)
                .connectTimeout(connectTimeout, TimeUnit.SECONDS)
                .writeTimeout(writeTimeout, TimeUnit.SECONDS)
                .pingInterval(pingInterval, TimeUnit.SECONDS)
                .addInterceptor(HeaderInterceptor())
                .addInterceptor(HttpLoggingInterceptor().apply {
                    level = HttpLoggingInterceptor.Level.BODY
                })
                .build()
        }
        return okHttpClient!!
    }

    private fun getGsonBuilder(): GsonBuilder {
        val builder = GsonBuilder()
        builder.registerTypeAdapter(
            Int::class.java,
            JsonDeserializer { json: JsonElement, _: Type?, _: JsonDeserializationContext? -> json.asInt } as JsonDeserializer<Int>)
        return builder
    }


    private inner class HeaderInterceptor : Interceptor {
        @Throws(IOException::class)
        override fun intercept(chain: Interceptor.Chain): Response {
            var request = chain.request()
            val builder =
                request.newBuilder()

            AppContext.url.toHttpUrl().let {
                val newUrl = request.url.newBuilder()
                newUrl.scheme(it.scheme)
                newUrl.host(it.host)
                newUrl.port(it.port)
                newUrl.encodedPath(request.url.encodedPath)
                builder.url(newUrl.build())
            }
            request = builder.build()
            return chain.proceed(request)
        }
    }
}